﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.Data;

namespace AzureInterop.Windows.Controls
{
	/// <summary>
	/// Interaction logic for MetadataView.xaml
	/// </summary>
	public partial class MetadataView : UserControl
	{
		#region Private data members
		private const string TABLE_NAME = "Metadata";
		private const string NAME_COLUMN_NAME = "Name";
		private const string VALUE_COLUMN_NAME = "Value";

		// Define all columns here that are to be shown in MetadataView's datagrid.
		private readonly System.Data.DataColumn[] m_columns = new System.Data.DataColumn[] {
			new System.Data.DataColumn(NAME_COLUMN_NAME),
			new System.Data.DataColumn(VALUE_COLUMN_NAME)
		};

		private System.Windows.Controls.TreeView m_treeview = null;
		private System.Data.DataTable m_table = null;
		#endregion

		#region Public constructors
		public MetadataView()
		{
			InitializeComponent();
		}
		#endregion

		#region Public properties
		public TreeView TreeView
		{
			get
			{
				return m_treeview;
			}
			set
			{
				if (null != value)
				{
					m_treeview = value;
					InitializeTreeViewHooks();
				}
			}
		}
		#endregion

		#region TreeView event handlers
		void m_treeview_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
		{
			AzureTreeViewItem tvi = ((TreeView)e.OriginalSource).SelectedItem as AzureTreeViewItem;
			if (null != tvi)
			{
				ShowMetadata(tvi);
			}
		}
		#endregion

		#region Public methods
		public void Show(System.Collections.Specialized.NameValueCollection metadata)
		{
			BuildDataTable(metadata);
			this.dataGrid.ItemsSource = m_table.DefaultView;
		}

		/// <summary>
		/// Displays metadata information for appropriate AzureTreeViewItems.
		/// </summary>
		/// <param name="tvi">A valid, appropriately populated AzureTreeViewItem</param>
		/// <exception cref="System.ArgumentNullException">Thrown when the input parameter is null</exception>
		/// <exception cref="System.ArgumentException">Thrown when the AzureTreeViewItem's Tag member is null or is not a recognized Azure object.</exception>
		public void ShowMetadata(AzureTreeViewItem tvi)
		{
			if (null == tvi)
				throw new ArgumentNullException();
			if (null == tvi.Tag)
				throw new ArgumentException();

			// Clear any existing metadata
			if (null != m_table)
				m_table.Clear();

			object azureObject = tvi.Tag;
			SetTypeLabel(azureObject);

			// Show metadata based on which type was stored in the Tag element
			if (azureObject.GetType().Equals(typeof(Microsoft.WindowsAzure.StorageClient.CloudBlob))
					|| azureObject.GetType().Equals(typeof(Microsoft.WindowsAzure.StorageClient.CloudBlockBlob))
					|| azureObject.GetType().Equals(typeof(Microsoft.WindowsAzure.StorageClient.CloudPageBlob)))
			{
				ShowMetadata(azureObject as Microsoft.WindowsAzure.StorageClient.CloudBlob);
			}
			else
			{
				if (azureObject.GetType().Equals(typeof(Microsoft.WindowsAzure.StorageClient.CloudBlobContainer)))
				{
					ShowMetadata(azureObject as Microsoft.WindowsAzure.StorageClient.CloudBlobContainer);
				}
				else
				{
					if (azureObject.GetType().Equals(typeof(Microsoft.WindowsAzure.CloudStorageAccount)))
					{
						ShowMetadata(azureObject as Microsoft.WindowsAzure.CloudStorageAccount);
					}
					else
					{
						Microsoft.WindowsAzure.StorageClient.CloudBlobDirectory cloudDir = azureObject as Microsoft.WindowsAzure.StorageClient.CloudBlobDirectory;
						System.Diagnostics.Debug.Assert(null != azureObject);
						// Do nothing; CloudDirectories don't have any interesting data to present
					}
				}
			}
		}
		#endregion

		#region Protected methods
		protected void SetTypeLabel(object o)
		{
			blobType.Content = o.GetType().Name.ToString();
			blobType.ToolTip = string.Format("Namespace: {0}", o.GetType().Namespace.ToString());
		}

		protected void SetNameAndType(Microsoft.WindowsAzure.CloudStorageAccount acct)
		{
			blobName.Text = acct.Credentials.AccountName;
			blobName.ToolTip = acct.BlobEndpoint;
		}

		protected void SetNameAndType(Microsoft.WindowsAzure.StorageClient.IListBlobItem blobItem)
		{
			blobName.Text = AzureInterop.CloudBlobHelper.GetName(blobItem);
			blobName.ToolTip = blobItem.Uri.ToString();
		}

		protected void ShowMetadata(Microsoft.WindowsAzure.CloudStorageAccount acct)
		{
			SetNameAndType(acct);
			System.Collections.Specialized.NameValueCollection nv = new System.Collections.Specialized.NameValueCollection();
			nv.Add("Azure Storage Account", acct.Credentials.AccountName);
			Show(nv);
		}

		protected void ShowMetadata(Microsoft.WindowsAzure.StorageClient.CloudBlob blob)
		{
				if (0 == blob.Metadata.Count)
				{
				    // retrieve blob's metadata
				    blob.FetchAttributes();
				}
				Show(blob.Metadata);

		}
		protected void ShowMetadata(Microsoft.WindowsAzure.StorageClient.CloudBlobContainer container)
		{
				if (0 == container.Metadata.Count)
				{
				    container.FetchAttributes();
				}
				Show(container.Metadata);

		}
		#endregion

		#region Private methods
		private void InitializeDataTable()
		{
			m_table = new System.Data.DataTable(TABLE_NAME);
			// Copy the column definitions to this table
			foreach (DataColumn column in m_columns)
			{
				m_table.Columns.Add(column);
			}
		}

		private void InitializeTreeViewHooks()
		{
			System.Diagnostics.Debug.Assert(null != m_treeview);

			// Watch for SelectedItemChanged events in the treeview
			m_treeview.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(m_treeview_SelectedItemChanged);
		}

		private void BuildDataTable(System.Collections.Specialized.NameValueCollection nv)
		{
			if (null == m_table)
			{
				InitializeDataTable();
			}

			// Remove any existing metadata
			m_table.Clear();

			// Add metadata to the table
			foreach (string key in nv.Keys)
			{
				System.Data.DataRow row = m_table.NewRow();
				row[NAME_COLUMN_NAME] = key.ToString();

				DateTime dt;
				if (DateTime.TryParse(nv[key], out dt))
				{
					row[VALUE_COLUMN_NAME] = dt.ToString();
				}
				else
				{
					row[VALUE_COLUMN_NAME] = nv[key].ToString();
				}

				m_table.Rows.Add(row);
			}
		}
		#endregion
	}
}
